package com.nageoffer.shortlink.admin.common.biz.user;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.nageoffer.shortlink.admin.common.convention.exception.ClientException;
import com.nageoffer.shortlink.admin.common.convention.result.Results;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Objects;

/**
 * 用户信息传输过滤器
 */
@RequiredArgsConstructor
public class UserTransmitFilter implements Filter {


    @SneakyThrows
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        String username = httpServletRequest.getHeader("username");
        if (StrUtil.isNotBlank(username)) {
            String userId = httpServletRequest.getHeader("userId");
            String realName = httpServletRequest.getHeader("realName");
            UserInfoDTO userInfoDTO = new UserInfoDTO(userId, username, realName);
            UserContext.setUser(userInfoDTO);
        }
        try {
            filterChain.doFilter(servletRequest, servletResponse);
        } finally {
            UserContext.removeUser();
        }
    }
}

    /*
     * 这是一个用户认证过滤器，主要功能：
     * 1. 对特定URI进行白名单放行
     * 2. 对用户注册请求特殊处理
     * 3. 对其他请求进行Token验证
     * 4. 将用户信息存入上下文供后续使用
     *//*

    *//* 使用StringRedisTemplate操作Redis *//*
    private final StringRedisTemplate stringRedisTemplate;

    *//* 定义不需要认证的白名单URI列表 *//*
    private static final List<String> IGNORE_URI = Lists.newArrayList(
            "/api/short-link/admin/v1/user/login",     // 用户登录接口
            "/api/short-link/admin/v1/user/has-username"  // 检查用户名是否存在接口
            *//* 被注释掉的URI "/api/short-link/admin/v1/title" *//*
    );

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {

        // 将ServletRequest转换为HttpServletRequest以获取更多HTTP相关信息
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;

        // 获取当前请求的URI
        String requestURI = httpServletRequest.getRequestURI();

        // 检查当前URI是否在白名单中，不在白名单的URI需要进行认证
        if (!IGNORE_URI.contains(requestURI)) {

            // 获取HTTP请求方法(GET/POST等)
            String method = httpServletRequest.getMethod();

            *//*
             * 特殊处理：如果是创建用户(POST)请求到/user接口，则跳过认证
             * 这是为了允许新用户注册而无需认证
             *//*
            if (!(Objects.equals(requestURI, "/api/short-link/admin/v1/user") && Objects.equals(method, "POST"))) {

                // 从请求头中获取用户名和token
                String username = httpServletRequest.getHeader("username");
                String token = httpServletRequest.getHeader("token");

                // 验证用户名和token是否都存在
                if (!StrUtil.isAllNotBlank(username, token)) {
                    // 如果任一为空，返回认证失败响应
                    returnJson((HttpServletResponse) servletResponse,
                            JSON.toJSONString(Results.failure(new ClientException(USER_TOKEN_FAIL))));
                    return;
                }

                // 从Redis中获取用户信息
                Object userInfoJsonStr;
                try {
                    // 使用用户名和token作为key从Redis Hash中获取用户信息
                    userInfoJsonStr = stringRedisTemplate.opsForHash().get(
                            USER_LOGIN_KEY + username, // Redis key前缀+用户名
                            token                       // Hash中的field
                    );

                    // 如果Redis中没有找到对应的用户信息，抛出异常
                    if (userInfoJsonStr == null) {
                        throw new ClientException(USER_TOKEN_FAIL);
                    }
                } catch (Exception ex) {
                    // Redis操作异常或用户信息不存在，返回认证失败
                    returnJson((HttpServletResponse) servletResponse,
                            JSON.toJSONString(Results.failure(new ClientException(USER_TOKEN_FAIL))));
                    return;
                }

                // 将Redis中的JSON用户信息反序列化为UserInfoDTO对象
                UserInfoDTO userInfoDTO = JSON.parseObject(userInfoJsonStr.toString(), UserInfoDTO.class);

                // 将用户信息存入ThreadLocal上下文，供后续业务逻辑使用
                UserContext.setUser(userInfoDTO);
            }
        }

        try {
            // 继续执行过滤器链中的下一个过滤器或目标资源
            filterChain.doFilter(servletRequest, servletResponse);
        } finally {
            // 确保在请求处理完成后清除ThreadLocal中的用户信息，防止内存泄漏
            UserContext.removeUser();
        }
    }

    *//**
     * 辅助方法：将JSON响应写回客户端
     * @param response HttpServletResponse对象
     * @param json 要返回的JSON字符串
     * @throws Exception 可能发生的IO异常
     *//*
    private void returnJson(HttpServletResponse response, String json) throws Exception {
        // 设置响应编码和内容类型
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=utf-8");

        // 使用try-with-resources确保PrintWriter正确关闭
        try (PrintWriter writer = response.getWriter()) {
            writer.print(json);
        }
    }*/
